import { Stmt } from "arkanalyzer";
import { ts, Location } from 'qvog-dsl';

import { HcEngineCapability, HcIssue } from './Defines';
import { Defects, IssueReport } from '../model/Defects';
import { BaseChecker } from '../Index';

function getAstNodeLocation(node: ts.Node): Location {
    const sourceFile = node.getSourceFile();

    const file = sourceFile.fileName;
    const start = sourceFile.getLineAndCharacterOfPosition(node.getStart());
    const end = sourceFile.getLineAndCharacterOfPosition(node.getEnd());

    return {
        file: file,
        range: {
            start: {
                line: start.line + 1,
                column: start.character + 1
            },
            end: {
                line: end.line + 1,
                column: end.character + 1
            },
        }
    };
}

function getIrNodeLocation(node: Stmt): Location {
    const line = node.getOriginPositionInfo().getLineNo();
    const column = node.getOriginPositionInfo().getColNo();
    return {
        file: 'not implemented',
        range: {
            start: {
                line: line,
                column: column
            },
            end: {
                line: line,
                column: column
            },
        }
    }
}

/**
 * Create a new instance of HcEngineCapability.
 *
 * This function MUST return different capability instances for different checkers.
 * As the `report` will be bind to the checker instance.
 *
 * All context-aware properties should be initialized later in
 * {@link postInitHcEngineCapability} when more information is available.
 *
 * @returns a new instance of HcEngineCapability.
 */
export function getHcEngineCapability(use: 'ast' | 'ir'): HcEngineCapability {
    const capability: HcEngineCapability = {
        name: 'homecheck',
        config: [],
        api: {
            getLocation: use === 'ast' ? getAstNodeLocation : getIrNodeLocation,
            report: undefined!
        },
        native: {
            rule: undefined!, // will be initialized when checker is loaded.
            checker: undefined! // the checker instance
        },
    };

    return capability;
}

/**
 * To complete the initialization of the HcEngineCapability.
 *
 * The capability of HomeCheck engine requires knowledge of the checker to ensure
 * proper behavior, especially for the `report` api. This is used to initialize
 * all context-aware properties of the capability.
 *
 * @param capability partially initialized engine capability
 * @param checker checker to bind to the capability
 */
export function postInitHcEngineCapability(
    capability: HcEngineCapability,
    checker: BaseChecker
): void {
    capability.native.checker = checker;
    capability.native.rule = checker.rule;
    capability.config = checker.rule.option;

    capability.api.report = (issue: HcIssue): void => {
        const defect = new Defects(
            issue.location.range.start.line,
            issue.location.range.start.column,
            issue.location.range.end.column,
            issue.description,
            issue.severity ?? 0,
            capability.native.rule.ruleId,
            issue.location.file,
            issue.docPath ?? '',
            true,
            false,
            false
        );
        capability.native.checker.issues.push(new IssueReport(defect, undefined));
    };
}